/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.das.commonmodel.entity.object.increment.extract;

import com.inspur.edp.cef.designtime.api.changecontrolrule.controlrule.cm.CommonDataTypeControlRule;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlruledef.cm.CommonDataTypeControlRuleDef;
import com.inspur.edp.cef.designtime.api.element.increment.extract.CommonFieldIncrementExtractor;
import com.inspur.edp.cef.designtime.api.entity.GspCommonDataType;
import com.inspur.edp.cef.designtime.api.entity.increment.ModifyEntityIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.extractor.ModifyEntityExtractor;
import com.inspur.edp.cef.designtime.api.increment.extractor.ExtractUtils;
import com.inspur.edp.cef.designtime.api.increment.extractor.MonkControlRule;
import com.inspur.edp.cef.designtime.api.json.CefNames;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.das.commonmodel.controlrule.CmEntityControlRule;
import com.inspur.edp.das.commonmodel.entity.GspCommonObject;
import com.inspur.edp.das.commonmodel.entity.element.increment.extract.CommonElementExtractor;
import com.inspur.edp.das.commonmodel.json.CommonModelNames;
import lombok.var;

import java.util.ArrayList;

public class ModifyCommonObjectExtractor extends ModifyEntityExtractor {

    public ModifyCommonObjectExtractor(){
        super();
    }

    public ModifyCommonObjectExtractor(boolean includeAll){
        super(includeAll);
    }
    @Override
    protected void extractExtendIncrement(ModifyEntityIncrement increment, GspCommonDataType oldDataType, GspCommonDataType newDataType, CommonDataTypeControlRule rule, CommonDataTypeControlRuleDef def) {
        extractBaseInfo(increment, (GspCommonObject) oldDataType, (GspCommonObject) newDataType, rule, def);
        extractChildObjs(increment, (GspCommonObject) oldDataType, (GspCommonObject) newDataType, rule, def);
        extractExtendObjectIncrement(increment, (GspCommonObject) oldDataType, (GspCommonObject) newDataType, rule, def);
    }

    private void extractBaseInfo(ModifyEntityIncrement increment, GspCommonObject oldDataType, GspCommonObject newDataType, CommonDataTypeControlRule rule, CommonDataTypeControlRuleDef def){
        if(includeAll)
            extractAllIncrement(increment, oldDataType, newDataType);
    }

    private void extractAllIncrement(ModifyEntityIncrement increment,GspCommonObject oldObj, GspCommonObject newObj){

//        SerializerUtils.writePropertyName(writer,CommonModelNames.RepositoryComps);
//        SerializerUtils.writePropertyValue_Object(writer,newObj.getRepositoryComps());

        var changes = increment.getChangeProperties();
        ExtractUtils.extractValue(changes, oldObj.getRefObjectName(), newObj.getRefObjectName(), CommonModelNames.RefObjectName, null,null);
        ExtractUtils.extractValue(changes, oldObj.getObjectType(), newObj.getObjectType(), CommonModelNames.ObjectType, null,null);
//        ExtractUtils.extractValue(changes, oldObj.getColumnGenerateID(), newObj.getColumnGenerateID(), CommonModelNames.ColumnGenerateID, null,null);
        ExtractUtils.extractValue(changes, oldObj.getOrderbyCondition(), newObj.getOrderbyCondition(), CommonModelNames.OrderbyCondition, null,null);
        ExtractUtils.extractValue(changes, oldObj.getFilterCondition(), newObj.getFilterCondition(), CommonModelNames.FilterCondition, null,null);
//        writeContainConstraints(writer, bizObject);
        ExtractUtils.extractValue(changes, oldObj.getIsReadOnly(), newObj.getIsReadOnly(), CommonModelNames.IsReadOnly, null,null);
        ExtractUtils.extractValue(changes, oldObj.getIsVirtual(), newObj.getIsVirtual(), CommonModelNames.IsVirtual, null,null);
        ExtractUtils.extractValue(changes, oldObj.getBelongModelID(), newObj.getBelongModelID(), CommonModelNames.BelongModelID, null,null);
        ExtractUtils.extractValue(changes, oldObj.getStateElementID(), newObj.getStateElementID(), CommonModelNames.StateElementID, null,null);

//        writeGspAssociationKeyCollection(writer, bizObject);

    }


    //region ChildObjs
    private void extractChildObjs(ModifyEntityIncrement increment, GspCommonObject oldObj, GspCommonObject newObj, CommonDataTypeControlRule rule, CommonDataTypeControlRuleDef def) {
        var newChildObjs = newObj.getContainChildObjects();
        var oldChildObjs = oldObj.getContainChildObjects();
        if (newChildObjs.size() < 1 && oldChildObjs.size() < 1)
            return;
        var extractor = createChildExtractor();

//        if(includeAll){
//            extractAllChildObjs(increment, oldObj, newObj, extractor);
//            return;
//        }

        if (newChildObjs.size() < 1) {
            extractAllDeleteIncrement(increment, oldObj, extractor, rule, def);
            return;
        }

        ArrayList<String> updateObjs = new ArrayList<>();

        for (var newChildObj : newChildObjs) {
            var oldChildObj = oldObj.getChildObjectById(newChildObj.getID());
            if (oldChildObj != null)
                updateObjs.add(oldChildObj.getID());
            CmEntityControlRule childObjRule = oldChildObj == null ? null:(CmEntityControlRule)rule.getChildRules().get(CommonModelNames.ChildObject).get(oldChildObj.getID());
            var childIncrement = extractor.extractorIncrement((GspCommonDataType) oldChildObj, (GspCommonDataType) newChildObj, childObjRule, def);
            if (childIncrement == null)
                continue;
            increment.getChildEntitis().put(((GspCommonDataType) newChildObj).getId(), childIncrement);
        }

        for (var oldChildObj : oldChildObjs) {
            if (updateObjs.contains(oldChildObj.getID()))
                continue;
            CmEntityControlRule childObjRule = (CmEntityControlRule)rule.getChildRules().get(CommonModelNames.ChildObject).get(oldChildObj.getID());
            var childIncrement = extractor.extractorIncrement((GspCommonDataType) oldChildObj, null, childObjRule, def);
            increment.getChildEntitis().put(oldChildObj.getID(), childIncrement);
        }

    }

    private void extractAllChildObjs(ModifyEntityIncrement increment, GspCommonObject oldObj, GspCommonObject newObj,CommonObjectIncrementExtractor extractor){
        extractAllDeleteIncrement(increment, oldObj, extractor, null,null);
        for (var newChildObj : newObj.getContainChildObjects()) {
            var childIncrement = extractor.extractorIncrement(null, (GspCommonDataType) newChildObj,null, null);
            increment.getChildEntitis().put(((GspCommonDataType) newChildObj).getId(), childIncrement);
        }

    }

    private void extractAllDeleteIncrement(ModifyEntityIncrement increment, GspCommonObject oldObj, CommonObjectIncrementExtractor extractor, CommonDataTypeControlRule rule, CommonDataTypeControlRuleDef def) {

        for (var childObj : oldObj.getContainChildObjects()) {
            CmEntityControlRule childObjRule = (CmEntityControlRule)rule.getChildRules().get(CommonModelNames.ChildObject).get(childObj.getID());
            var childIncrement = extractor.extractorIncrement((GspCommonDataType) childObj, null, childObjRule, def);
            increment.getChildEntitis().put(childObj.getID(), childIncrement);
        }

    }

    //endregion

    protected CommonObjectIncrementExtractor createChildExtractor() {
        return new CommonObjectIncrementExtractor(includeAll);
    }


    protected void extractExtendObjectIncrement(ModifyEntityIncrement increment, GspCommonDataType oldDataType, GspCommonDataType newDataType, CommonDataTypeControlRule rule, CommonDataTypeControlRuleDef def) {

    }

    @Override
    protected final CommonFieldIncrementExtractor createFieldExtractor() {
        return getCommonElementExtractor();
    }

    protected CommonElementExtractor getCommonElementExtractor() {
        return new CommonElementExtractor(includeAll);
    }
}
